
#include "netser.hpp"
#include <arpa/inet.h>
#include <cstring>
#include <iostream>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>

netser::netser(int port)
{
	int ret = 0;
	struct sockaddr_in address;
	int addrlen = sizeof(address);

	ser_port = port;

	ser_fd = socket(AF_INET, SOCK_DGRAM, 0);
	if (ser_fd < 0) {
		std::cerr << "Could not create socket" << std::endl;
	}

	memset(&address, 0, sizeof(address));
	address.sin_family = AF_INET;
	address.sin_addr.s_addr = INADDR_ANY;
	address.sin_port = htons(ser_port);
	ret = bind(ser_fd, (struct sockaddr*)&address, sizeof(address));
	if (ret < 0) {
		perror("bind failed");
		exit(EXIT_FAILURE);
	}
}

netser::~netser()
{
	close(ser_fd);
}

int netser::send(char* buf, size_t len, struct sockaddr_in* addr)
{
	int ret = 0;

	ret = sendto(ser_fd, (const char*)buf, len, MSG_CONFIRM, (struct sockaddr*)addr, sizeof(struct sockaddr_in));
	if (ret < 0) {
		std::cerr << "Send failed, ret = " << ret << std::endl;
		return -1;
	}

	return 0;
}

int netser::recv(char* buf, size_t size, struct sockaddr_in* addr)
{
	int ret = 0;
	socklen_t len = 0;

	len = sizeof(struct sockaddr_in); // 这行很关键，没有这行对端的ip接受会出错
	ret = recvfrom(ser_fd, (char*)buf, size, MSG_WAITALL, (struct sockaddr*)addr, &len);
	if (ret < 0) {
		std::cerr << "Receive failed" << std::endl;
		return -1;
	}
	buf[ret] = '\0';

	return 0;
}

int netser::start()
{
	if (!handle.joinable()) {
		running = true;
		handle = std::thread(&netser::thread, this);
	}

	return 0;
}

int netser::stop()
{
	if (handle.joinable()) {
		running = false;
		handle.join();
	}

	return 0;
}

void netser::thread()
{
	int ret = 0;
	size_t size = 1024;
	char* buf = NULL;
	struct sockaddr_in cli_addr;
	unsigned addrlen = 0;

	buf = new char[1024];
	memset(&cli_addr, 0, sizeof(struct sockaddr_in));

	while (running) {
		ret = recv(buf, size, &cli_addr);
		if (ret < 0) {
			std::cerr << "err: recv()" << std::endl;
		}
		std::cout << "Received: " << buf << inet_ntoa(cli_addr.sin_addr) << "/" << cli_addr.sin_port << std::endl;
		send(buf, strlen(buf), &cli_addr);
	}

	delete[] buf;
}
